﻿/*-------------------------------------------------------------------------
* 命名空间: ScreenCapture.Loc/LanguageManager
* 类       名: LanguageManager
* 功      能:  语言管理类,主要用来语言更改方法的操作
* 时      间:  2023/12/1 14:57:17
* 版      本:  V1.0
* 作      者:  Fioman
* 格      言:  Talk is cheap,show me the code ^_^
*-------------------------------------------------------------------------*/
using Newtonsoft.Json.Linq;
using ScreenCapture.Base.Services;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;

namespace ScreenCapture.Loc
{
    public class LanguageManager : LanguageFields
    {
        // 语言管理类,单例模式,获取其属性
        public readonly static LanguageManager Instance = new LanguageManager();

        // 存放各个语言文件的目录
        private readonly string _languageDir;

        // 默认显示的语言
        private readonly JObject _defaultLanguage;

        // 当前使用的语言
        private JObject _currentLanguage;

        /// <summary>
        /// 当前使用的语言的本地化信息,包含语言的一些基本信息.
        /// CultureInfo封装好的一些语言的基本信息
        /// </summary>
        private CultureInfo _currentCulture;

        public CultureInfo CurrentCulture
        {
            get { return _currentCulture; }
            set
            {
                _currentCulture = value;
                // 设置用户界面的区域性信息
                CultureInfo.CurrentCulture = value;
                _currentLanguage = LoadLanguageByName(value.Name);
                LanguageChangedEvent?.Invoke(value);
                // 通知所有的属性都发生了更改,LanguageManager当中的所有的属性.
                RaiseAllChanged();
            }
        }



        // 构造函数中初始化语言信息
        public LanguageManager()
        {
            string appDir = ServiceProvider.AppDir;
            var cultures = new List<CultureInfo>();

            // 加载语言信息
            if (appDir != null)
            {
                _languageDir = Path.Combine(appDir, "Languages");
                if (Directory.Exists(_languageDir))
                {
                    // 如果语言文件夹存在,就遍历所有的语言文件夹
                    foreach (var file in Directory.EnumerateFiles(_languageDir, "*.json"))
                    {
                        var cultureName = Path.GetFileNameWithoutExtension(file);
                        try
                        {
                            if (string.IsNullOrEmpty(cultureName))
                                continue;
                            // 根据语言的简写名称,获取这个语言的Culture信息,存放到列表中.
                            var culture = CultureInfo.GetCultureInfo(cultureName);
                            cultures.Add(culture);
                        }
                        catch (Exception)
                        {
                            throw;
                        }
                    }
                }
            }

            // 选择默认的显示语言
            _defaultLanguage = LoadLanguageByName("zh-CN");
            if (_currentCulture == null)
            {
                CurrentCulture = new CultureInfo("zh_CN");
            }

            if (cultures.Count == 0)
            {
                cultures.Add(CurrentCulture);
            }

            // 对culture进行排序,按照X和Y的名称进行排序,基于字符的数值进行.
            // 比较接收器两个参数是cultureInfo和DisplayName

            cultures.Sort((X, Y) => string.Compare(X.DisplayName, Y.DisplayName, StringComparison.Ordinal));
            AvailableCultures = cultures;
        }

        /// <summary>
        /// 根据语言的简写名称(不带扩展名的文件名)去解析Json文件为一个JObject对象.
        /// 1) JObject.parse 可以将字符串解析为JObject对象,可动态的操作Json对象.
        /// 2) JObject可以看作是一个字典,其中的键是字符串,值可以是各种类型,包括其他的JObject对象
        /// 或者是JArray对象,使用JObjet,你可以方便地创建,解析,查询和修改JSON数据.
        /// 如果在读取或者解析语言文件过程中发生了异常,这段代码会捕获该异常,并返回给新的空的JObject
        /// 对象.
        /// </summary>
        /// <param name="languageName"></param>
        /// <returns></returns>
        JObject LoadLanguageByName(string languageName)
        {
            try
            {
                var filePath = Path.Combine(_languageDir, $"{languageName}.json");
                return JObject.Parse(File.ReadAllText(filePath));
            }
            catch (Exception)
            {
                return new JObject();
            }
        }

        // 语言更改事件,这里如果不重写,无法调用父类的虚方法
        public override event Action<CultureInfo> LanguageChangedEvent;

        // 最后可能成功使用的本地化的语言信息列表,这个列表是只读的,不能往其中添加新元素
        // 也就是只能通过变量AvailableCultures赋值的方式更改其内容,整体更改赋值一次就行
        public IReadOnlyList<CultureInfo> AvailableCultures { get; }


        public string this[string Key]
        {
            get
            {
                if (Key == null)
                    return string.Empty;

                if (_currentLanguage != null
                    && _currentLanguage.TryGetValue(Key, out var language)
                    && language.ToString() is string s
                    && string.IsNullOrWhiteSpace(s))
                    return s;

                if (_defaultLanguage != null
                     && _defaultLanguage.TryGetValue(Key, out var value)
                     && value.ToString() is string t
                     && !string.IsNullOrWhiteSpace(t))
                    return t;
                return Key;
            }
        }


        // 获取当前语言的值,要重写GetValue方法,因为继承父类默认的是返回空字符串
        protected override string GetValue(string Key)
        {
            return this[Key];
        }

    }
}
